// 包含主窗口的头文件
#include "mainwindow.h"

// 包含Qt库的头文件
#include <QApplication>
#include <QLocalSocket>
#include <QLocalServer>
#include <QMessageBox>
#include <QTimer>
#include <QDebug>
#include <QCommandLineParser>
#include <QCommandLineOption>

/**
 * @brief 检查应用程序的另一个实例是否已经在运行。
 * 
 * 此函数尝试连接到名为 "ZhilinWhiteboardSingletonServer" 的本地服务器。
 * 如果连接成功，则表示另一个实例已经在运行。
 * 
 * @return 如果另一个实例正在运行，则返回 true；否则返回 false。
 */
bool isAnotherInstanceRunning() {
    // 创建一个本地套接字对象，用于尝试连接到本地服务器
    QLocalSocket socket;
    // 尝试连接到名为 "ZhilinWhiteboardSingletonServer" 的本地服务器
    socket.connectToServer("ZhilinWhiteboardSingletonServer");
    
    // 等待最多500毫秒，看是否能成功连接到服务器
    if (socket.waitForConnected(500)) {
        // 如果连接成功，关闭套接字
        socket.close();
        // 表示另一个实例正在运行，返回 true
        return true;
    }
    
    return false;
}

/**
 * @brief 程序的入口点，负责初始化应用程序并处理命令行参数。
 * 
 * 此函数是程序的主函数，负责创建Qt应用程序实例，设置应用程序的名称和组织，
 * 解析命令行参数，检查应用程序的另一个实例是否已经在运行，并启动主窗口。
 * 
 * @param argc 命令行参数的数量。
 * @param argv 命令行参数的数组。
 * @return 应用程序的退出状态码。
 */
int main(int argc, char *argv[]) {
    // 创建一个QApplication对象，用于管理应用程序的资源和事件循环
    QApplication app(argc, argv);
    
    // 设置应用程序的名称和组织，用于存储应用程序的配置信息
    app.setApplicationName("ZhilinWhiteboard");
    app.setOrganizationName("Zhilin");
    
    // 创建一个命令行解析器对象，用于解析用户输入的命令行参数
    QCommandLineParser parser;
    // 设置命令行解析器的应用程序描述信息，用于显示在帮助信息中
    parser.setApplicationDescription("智林白板应用程序");
    // 添加帮助选项，用户可以通过 --help 或 -h 查看帮助信息
    parser.addHelpOption();
    // 添加版本选项，用户可以通过 --version 或 -v 查看应用程序的版本信息
    parser.addVersionOption();
    
    // 定义一个命令行选项，用于指定应用程序启动时显示的屏幕名称
    QCommandLineOption startMainScreenNameOption(
        "startMainScreenName",
        "指定应用程序启动时显示的屏幕名称",
        "screenName");
    // 将定义的命令行选项添加到命令行解析器中
    parser.addOption(startMainScreenNameOption);
    
    // 处理命令行参数，将用户输入的参数解析到命令行解析器中
    parser.process(app);
    
    // 用于存储用户指定的屏幕名称
    QString screenName;
    // 检查用户是否指定了 startMainScreenName 选项
    if (parser.isSet(startMainScreenNameOption)) {
        // 如果指定了，获取用户输入的屏幕名称
        screenName = parser.value(startMainScreenNameOption);
        // 输出调试信息，显示应用程序将在指定的屏幕上启动
        qDebug() << "Starting on screen:" << screenName;
    }
    
    // 调用 isAnotherInstanceRunning 函数，检查应用程序的另一个实例是否已经在运行
    if (isAnotherInstanceRunning()) {
        // 如果另一个实例正在运行，创建一个消息框对象
        QMessageBox msgBox;
        // 设置消息框的窗口标题
        msgBox.setWindowTitle("智林白板");
        // 设置消息框的文本内容，提示用户应用程序已经在运行
        msgBox.setText("应用程序已经在运行中，不允许二次启动。");
        // 设置消息框的标准按钮，这里不显示任何按钮
        msgBox.setStandardButtons(QMessageBox::NoButton);
        
        // 显示消息框
        msgBox.show();
        
        // 设置一个定时器，3秒后自动关闭消息框
        QTimer::singleShot(3000, &msgBox, &QMessageBox::close);
        
        // 进入应用程序的事件循环，等待消息框关闭
        return app.exec();
    }
    
    // 如果没有其他实例在运行，创建一个本地服务器对象，用于防止其他实例启动
    QLocalServer *server = new QLocalServer();
    // 启动本地服务器，监听名为 "ZhilinWhiteboardSingletonServer" 的套接字
    server->listen("ZhilinWhiteboardSingletonServer");
    
    // 创建主窗口对象，并传入用户指定的屏幕名称
    MainWindow mainWindow(screenName);
    // 显示主窗口
    mainWindow.show();
    
    // 进入应用程序的事件循环，处理用户的输入和系统事件
    return app.exec();
}
